package reflection;

import org.junit.Test;
import reflection.entity.SubClass;
import reflection.entity.SuperClass;
import reflection.service.MyInterface;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Comparator;
import java.util.Properties;

/**
 * @author liweimin
 * @date 2021/4/6 18:23
 * @description 反射测试
 * @since
 */
public class ReflectionTest {


    /**
     * 获取Class类测试
     *
     * @throws ClassNotFoundException
     */
    @Test
    public void test1() throws ClassNotFoundException {
        Class clazz = String.class;

        String string = "a";

        Class clazz1 = string.getClass();

        Class clazz2 = Class.forName("java.lang.String");

        Class clazz3 = Class.forName("reflection.entity.User");

        ClassLoader classLoader = this.getClass().getClassLoader();
        Class clazz4 = classLoader.loadClass("reflection.entity.User");
        System.out.println(clazz4);
    }

    @Test
    public void test2() {
        Class<Object> objectClass = Object.class;
        Class<Comparator> comparatorClass = Comparator.class;
        Class<String[]> aClass = String[].class;
        System.out.println(aClass.getName());
        System.out.println(aClass.getSimpleName());
        Class<Override> overrideClass = Override.class;
        Class<Integer> integerClass = int.class;
        Class<Void> voidClass = void.class;
        Class<Byte> type1 = Byte.TYPE;
        //基本数据类型的包装类才有
        Class<Integer> type = Integer.TYPE;
        int[] ints = new int[100];
        Integer[] integers = new Integer[100];
        int[] ints1 = new int[1000];
        System.out.println(ints1.getClass() == ints.getClass());
        Class<? extends Integer[]> aClass1 = integers.getClass();
        Class<? extends int[]> aClass2 = ints.getClass();

    }

    @Test
    public void test3() {
        //只会触发父类的初始化 m定义在父类中
        System.out.println(SubClass.m);
    }

    @Test
    public void test4() {
        //通过数组引用类不会调用父类初始化，调用的是这个数组类的初始化 [Lreflection.entity.SuperClass; 由虚拟机自动生成，继承于Object类，创建动作由字节码指令newarray触发
        SuperClass[] superClasses = new SuperClass[100];
        System.out.println(superClasses.getClass().getName());
    }

    @Test
    public void test5() {
        //使用字面量定义的类变量存放在常量池中，未调用静态代码块去初始化数据
        System.out.println(SuperClass.HELLOWORLD);
        //非字面量定义的仍需要静态代码块初始化数据
        System.out.println(SuperClass.HELLOWORLD1);

    }

    @Test
    public void test6() {
        System.out.println(SubClass.a);
    }

    @Test
    public void test7() throws ClassNotFoundException {
        //获取一个系统类加载器（也叫AppClassLoader）
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);

        //获取系统类加载器的父类--->扩展类加载器
        ClassLoader extensionClassLoader = systemClassLoader.getParent();
        System.out.println(extensionClassLoader);

        //获取引导类加载器(无法获取)---> 扩展类加载器的父类
        ClassLoader bootstrapClassLoader = extensionClassLoader.getParent();
        System.out.println(bootstrapClassLoader);

        //当前类是哪个加载器加载的
        Class clazz = this.getClass();

        System.out.println(clazz.getName());

        System.out.println(clazz.getClassLoader());


        //Object类是哪个加载器加载的
        Class clazz1 = Class.forName("java.lang.Object");

        ClassLoader objectClassLoader = clazz1.getClassLoader();

        //引导加载器加载的
        System.out.println(objectClassLoader);

    }

    @Test
    public void test8() {
        //类加载器可以加载的路径---->双亲委派机制
        System.out.println(System.getProperty("java.class.path"));
    }

    @Test
    public void test9() throws IOException {
        Properties properties = new Properties();
        FileInputStream fileInputStream = new FileInputStream("src\\reflection\\resource\\test.properties");
        properties.load(fileInputStream);
        System.out.println(properties.stringPropertyNames());
        System.out.println(properties.getProperty("user"));
        fileInputStream.close();
    }

    @Test
    public void test10() throws IOException {
        Properties properties = new Properties();
        //报异常，因为默认配置文件在当前module\src下
//        InputStream in = this.getClass().getClassLoader().getResourceAsStream("src\\reflection\\resource\\test.properties");
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("1.properties");
        properties.load(in);
        System.out.println(properties.stringPropertyNames());
        System.out.println(properties.getProperty("user"));
        in.close();
    }

    @Test
    public void test11() {
        System.out.println(MyInterface.class);
    }
}
